<template>
	<view class="piaoyi-tabs" :style="[ tabStyle ]">
		<view :id="id">
			<scroll-view scroll-x :class="[`piaoyi-tabs-view`]" :scroll-left="scrollLeft" scroll-with-animation>
				<view :class="[
          `piaoyi-tabs-box`,
          !isScroll && `piaoyi-tabs-flex`
        ]">
					<view v-for="(item, index) in list" :id="`piaoyi-tabs-item-${index}`" :key="index" :class="[
            `piaoyi-tabs-item`,
            index === current && `piaoyi-tabs-item-active`
          ]" :style="[tabItemStyle(index)]" @tap="clickTab(index)">{{ item[name || 'name'] }}
					</view>
					<view v-if="showBar" class="piaoyi-tabs-bar" :style="[tabBarStyle]" />
				</view>
			</scroll-view>
		</view>
	</view>
</template>
<script>
	export default {
		name: 'Tabs',
		props: {
			isScroll: {
				type: Boolean,
				default: true,
			},
			// 需循环的标签列表
			list: {
				type: Array,
				default: () => [],
			},
			// 当前活动tab的索引
			current: {
				type: [Number, String],
				default: 0,
			},
			// 导航栏的宽度
			width: {
				type: String,
				default: '100%',
			},
			// 导航栏的高度和行高
			height: {
				type: [String, Number],
				default: 64,
			},
			// 字体大小
			fontSize: {
				type: [String, Number],
				default: 30,
			},
			// 过渡动画时长, 单位s
			duration: {
				type: [String, Number],
				default: 0.35,
			},
			// 选中项的主题颜色
			activeColor: {
				type: String,
				default: '#24c789',
			},
			// 未选中项的默认颜色
			inactiveColor: {
				type: String,
				default: '#333',
			},
			// 是否显示底部的滑块
			showBar: {
				type: Boolean,
				default: false,
			},
			barWidth: {
				type: [String, Number],
				default: 40,
			},
			barHeight: {
				type: [String, Number],
				default: 6,
			},
			gutter: {
				type: [String, Number],
				default: 32,
			},
			bgColor: String,
			name: {
				type: String,
				default: 'name',
			},
			bold: {
				type: [Boolean, String, Number],
				default: true,
			},
			activeItemStyle: {
				type: Object,
				default: () => {},
			},
			barStyle: {
				type: Object,
				default: () => {},
			},
			itemWidth: {
				type: [Number, String],
				default: 'auto',
			},
			vibrateShort: {
				type: Boolean,
				default: true,
			}
		},
		data() {
			return {
				id: 'piaoyi' + this.guid(),
				scrollLeft: 0,
				tabQueryInfo: [],
				componentWidth: 0,
				scrollBarLeft: 0,
				parentLeft: 0,
				currentIndex: this.current,
				barFirstTimeMove: true
			};
		},
		computed: {
			tabStyle() {
				const style = {};
				if (this.bgColor) style.backgroundColor = this.bgColor;
				style.width = this.width;
				return style;
			},
			tabBarStyle() {
				const style = {
					width: `${this.barWidth}rpx`,
					transform: `translate(${this.scrollBarLeft}px, -100%)`,
					// 滑块在页面渲染后第一次滑动时，无需动画效果
					'transition-duration': `${this.barFirstTimeMove ? 0 : this.duration }s`,
					'background-color': this.activeColor,
					height: `${this.barHeight}rpx`,
					// 设置一个很大的值，它会自动取能用的最大值，不用高度的一半，是因为高度可能是单数，会有小数出现
					'border-radius': `${this.barHeight / 2}px`,
				};
				Object.assign(style, this.barStyle);
				return style;
			},
			tabItemStyle() {
				return (index) => {
					let style = {
						height: `${this.height}rpx`,
						'line-height': `${this.height}rpx`,
						'font-size': `${this.fontSize}rpx`,
						transition: `color .18s，background ${this.duration}s`,
						padding: this.isScroll ? `0 ${this.gutter}rpx` : '',
						flex: this.isScroll ? 'auto' : '1',
						width: this.validValue(this.itemWidth),
					};
					if (index === this.currentIndex && this.bold) {
						if (typeof this.bold === 'boolean') {
							style.fontWeight = 'bold';
						} else {
							style.fontWeight = this.bold;
						}
					}
					if (index === this.currentIndex) {
						style.color = this.activeColor;
						// 给选中的tab item添加外部自定义的样式
						style = Object.assign(style, this.activeItemStyle);
					} else {
						style.color = this.inactiveColor;
					}
					return style;
				};
			},
		},
		watch: {
			list(n, o) {
				if (n.length !== o.length) {
					this.currentIndex = this.current;
					this.$nextTick(() => {
						this.init();
					});
				}
			},
			current: {
				immediate: true,
				handler(nVal, oVal) {
					this.$nextTick(() => {
						this.currentIndex = nVal;
						this.scrollByIndex();
					});
				},
			},
		},
		mounted() {
			this.init();
		},
		methods: {
			guid() {
				return 'xxxxxxxx'.replace(/[xy]/g, function(c) {
					var r = Math.random() * 16 | 0,
						v = c == 'x' ? r : (r & 0x3 | 0x8);
					return v.toString(16);
				});
			},
			validValue(value = 'auto', unit = 'rpx') {
				return !isNaN(parseFloat(value)) ? `${value}${unit}` : value;
			},
			async init() {
				const res = await this.handleGetRect(`#${this.id}`);
				this.parentLeft = res.left;
				this.componentWidth = res.width;
				this.getTabRect();
			},
			handleGetRect(selector, all) {
				return new Promise(resolve => {
					uni
						.createSelectorQuery()
						.in(this)[all ? "selectAll" : "select"](selector)
						.boundingClientRect(rect => {
							if (all && Array.isArray(rect) && rect.length) {
								resolve(rect);
							}
							if (!all && rect) {
								resolve(rect);
							}
						})
						.exec();
				});
			},
			clickTab(index) {
				if (index === this.currentIndex) return;
				this.$emit('change', index);
				if (this.vibrateShort) uni.vibrateShort();
			},
			getTabRect() {
				const query = uni.createSelectorQuery().in(this);
				for (const i in this.list) {
					query.select(`#piaoyi-tabs-item-${i}`).fields({
						size: true,
						rect: true,
					});
				}
				query.exec((res) => {
					this.tabQueryInfo = res;
					this.scrollByIndex();
				});
			},
			scrollByIndex() {
				const tabInfo = this.tabQueryInfo[this.currentIndex];
				if (!tabInfo) return;
				const tabWidth = tabInfo.width;
				const offsetLeft = tabInfo.left - this.parentLeft;
				const scrollLeft = offsetLeft - (this.componentWidth - tabWidth) / 2;
				this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft;
				const left = tabInfo.left + tabInfo.width / 2 - this.parentLeft;
				this.scrollBarLeft = left - uni.upx2px(this.barWidth) / 2;
				if (this.barFirstTimeMove) {
					setTimeout(() => {
						this.barFirstTimeMove = false;
					}, 100);
				}
			},
		},
	};
</script>
<style lang="scss" scoped>
	.piaoyi-tabs {
		&-view {
			width: 100%;
			white-space: nowrap;
			position: relative;
		}

		&-box {
			position: relative;
			/* #ifdef MP-TOUTIAO */
			white-space: nowrap;
			/* #endif */
		}

		&-item {
			/* #ifndef APP-NVUE */
			display: inline-block;
			/* #endif */
			text-align: center;
			transition-property: background-color, color;

			&-active {
				color: #fff;
				transition-timing-function: ease-in-out;
			}
		}

		&-bar {
			position: absolute;
			bottom: 0;
		}

		&-flex {
			display: flex;
			justify-content: space-between;
		}
	}

	/* #ifndef APP-NVUE */
	::-webkit-scrollbar,
	::-webkit-scrollbar,
	::-webkit-scrollbar {
		display: none;
		width: 0 !important;
		height: 0 !important;
		-webkit-appearance: none;
		background: transparent;
	}

	/* #endif */
	/* #ifdef H5 */
	// 通过样式穿透，隐藏H5下，scroll-view下的滚动条
	scroll-view ::v-deep ::-webkit-scrollbar {
		display: none;
		width: 0 !important;
		height: 0 !important;
		-webkit-appearance: none;
		background: transparent;
	}

	/* #endif */
	// 
</style>
